Implement bookmark renaming (#136216, Sean Middleditch)
authorMatthias Clasen <mclasen@redhat.com>
Tue, 22 Mar 2005 20:23:19 +0000 (20:23 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Tue, 22 Mar 2005 20:23:19 +0000 (20:23 +0000)
2005-03-22  Matthias Clasen  <mclasen@redhat.com>

Implement bookmark renaming  (#136216, Sean Middleditch)

* gtk/gtkfilesystem.h (struct _GtkFileSystemIface): Add
get_bookmark_label and set_bookmark_label vfuncs.

* gtk/gtkfilesystem.h:
* gtk/gtkfilesystem.c (gtk_file_system_set_bookmark_label):
(gtk_file_system_get_bookmark_label): Wrappers for the
vfuncs.

* gtk/gtk.symbols: Add new exported symbols.

* gtk/gtkfilesystemunix.c (gtk_file_system_unix_set_bookmark_label):
(gtk_file_system_unix_get_bookmark_label): Implementations
for the Unix backend.

* gtk/gtkfilechooserdefault.c: Add a context menu to
the bookmarks pane, and allow to rename bookmarks.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
gtk/gtk.symbols
gtk/gtkfilechooserdefault.c
gtk/gtkfilesystem.c
gtk/gtkfilesystem.h
gtk/gtkfilesystemunix.c

index a6f7d951de06f23171f44463b1b3d609892ae630..9d3c32114f08aa956d01990c1fdccec3a027e721 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2005-03-22  Matthias Clasen  <mclasen@redhat.com>
+
+       Implement bookmark renaming  (#136216, Sean Middleditch)
+       
+       * gtk/gtkfilesystem.h (struct _GtkFileSystemIface): Add 
+       get_bookmark_label and set_bookmark_label vfuncs.
+
+       * gtk/gtkfilesystem.h:
+       * gtk/gtkfilesystem.c (gtk_file_system_set_bookmark_label): 
+       (gtk_file_system_get_bookmark_label): Wrappers for the
+       vfuncs.
+
+       * gtk/gtk.symbols: Add new exported symbols.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_set_bookmark_label): 
+       (gtk_file_system_unix_get_bookmark_label): Implementations
+       for the Unix backend.
+
+       * gtk/gtkfilechooserdefault.c: Add a context menu to
+       the bookmarks pane, and allow to rename bookmarks.
+
 2005-03-22  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkpathbar.c (gtk_path_bar_unmap): 
index a6f7d951de06f23171f44463b1b3d609892ae630..9d3c32114f08aa956d01990c1fdccec3a027e721 100644 (file)
@@ -1,3 +1,24 @@
+2005-03-22  Matthias Clasen  <mclasen@redhat.com>
+
+       Implement bookmark renaming  (#136216, Sean Middleditch)
+       
+       * gtk/gtkfilesystem.h (struct _GtkFileSystemIface): Add 
+       get_bookmark_label and set_bookmark_label vfuncs.
+
+       * gtk/gtkfilesystem.h:
+       * gtk/gtkfilesystem.c (gtk_file_system_set_bookmark_label): 
+       (gtk_file_system_get_bookmark_label): Wrappers for the
+       vfuncs.
+
+       * gtk/gtk.symbols: Add new exported symbols.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_set_bookmark_label): 
+       (gtk_file_system_unix_get_bookmark_label): Implementations
+       for the Unix backend.
+
+       * gtk/gtkfilechooserdefault.c: Add a context menu to
+       the bookmarks pane, and allow to rename bookmarks.
+
 2005-03-22  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkpathbar.c (gtk_path_bar_unmap): 
index a6f7d951de06f23171f44463b1b3d609892ae630..9d3c32114f08aa956d01990c1fdccec3a027e721 100644 (file)
@@ -1,3 +1,24 @@
+2005-03-22  Matthias Clasen  <mclasen@redhat.com>
+
+       Implement bookmark renaming  (#136216, Sean Middleditch)
+       
+       * gtk/gtkfilesystem.h (struct _GtkFileSystemIface): Add 
+       get_bookmark_label and set_bookmark_label vfuncs.
+
+       * gtk/gtkfilesystem.h:
+       * gtk/gtkfilesystem.c (gtk_file_system_set_bookmark_label): 
+       (gtk_file_system_get_bookmark_label): Wrappers for the
+       vfuncs.
+
+       * gtk/gtk.symbols: Add new exported symbols.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_set_bookmark_label): 
+       (gtk_file_system_unix_get_bookmark_label): Implementations
+       for the Unix backend.
+
+       * gtk/gtkfilechooserdefault.c: Add a context menu to
+       the bookmarks pane, and allow to rename bookmarks.
+
 2005-03-22  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkpathbar.c (gtk_path_bar_unmap): 
index bed716f016cc5e799439409e264c1b33e5c61c25..05d4a5f3ba2f058b5458084dcdceff6fa5731205 100644 (file)
@@ -1331,6 +1331,8 @@ gtk_file_system_volume_get_display_name
 gtk_file_system_volume_get_is_mounted
 gtk_file_system_volume_mount
 gtk_file_system_volume_render_icon
+gtk_file_system_get_bookmark_label
+gtk_file_system_set_bookmark_label
 #endif
 #endif
 
index afcfbbb4d92408e8b6b5d50e415f491a729b5f73..0e7055c44ea49f2d24dfb7c0f4fcde7a80244a34 100644 (file)
@@ -120,6 +120,9 @@ struct _GtkFileChooserDefault
   GtkWidget *browse_shortcuts_tree_view;
   GtkWidget *browse_shortcuts_add_button;
   GtkWidget *browse_shortcuts_remove_button;
+  GtkWidget *browse_shortcuts_popup_menu;
+  GtkWidget *browse_shortcuts_popup_menu_remove_item;
+  GtkWidget *browse_shortcuts_popup_menu_rename_item;
   GtkWidget *browse_files_tree_view;
   GtkWidget *browse_files_popup_menu;
   GtkWidget *browse_files_popup_menu_add_shortcut_item;
@@ -1323,6 +1326,7 @@ shortcuts_append_paths (GtkFileChooserDefault *impl,
 {
   int start_row;
   int num_inserted;
+  gchar *label;
 
   /* As there is no separator now, we want to start there.
    */
@@ -1341,9 +1345,13 @@ shortcuts_append_paths (GtkFileChooserDefault *impl,
          !gtk_file_system_path_is_local (impl->file_system, path))
        continue;
 
+      label = gtk_file_system_get_bookmark_label (impl->file_system, path);
+
       /* NULL GError, but we don't really want to show error boxes here */
-      if (shortcuts_insert_path (impl, start_row + num_inserted, FALSE, NULL, path, NULL, TRUE, NULL))
+      if (shortcuts_insert_path (impl, start_row + num_inserted, FALSE, NULL, path, label, TRUE, NULL))
        num_inserted++;
+
+      g_free (label);
     }
 
   return num_inserted;
@@ -2289,6 +2297,24 @@ bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl)
   g_free (name);
 }
 
+static void
+shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl)
+{
+  GtkTreeIter iter;
+  gboolean removable = FALSE;
+
+  if (impl->browse_shortcuts_popup_menu == NULL)
+    return;
+
+  if (shortcuts_get_selected (impl, &iter))
+    gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
+                       SHORTCUTS_COL_REMOVABLE, &removable,
+                       -1);
+
+  gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_remove_item, removable);
+  gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_rename_item, removable);
+}
+
 /* GtkWidget::drag-begin handler for the shortcuts list. */
 static void
 shortcuts_drag_begin_cb (GtkWidget             *widget,
@@ -2809,6 +2835,7 @@ shortcuts_selection_changed_cb (GtkTreeSelection      *selection,
                                GtkFileChooserDefault *impl)
 {
   bookmarks_check_remove_sensitivity (impl);
+  shortcuts_check_popup_sensitivity (impl);
 }
 
 static gboolean
@@ -2847,6 +2874,170 @@ tree_view_keybinding_cb (GtkWidget             *tree_view,
   return FALSE;
 }
 
+/* Callback used when the file list's popup menu is detached */
+static void
+shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget,
+                               GtkMenu   *menu)
+{
+  GtkFileChooserDefault *impl;
+  
+  impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
+  g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
+
+  impl->browse_shortcuts_popup_menu = NULL;
+  impl->browse_shortcuts_popup_menu_remove_item = NULL;
+  impl->browse_shortcuts_popup_menu_rename_item = NULL;
+}
+
+static void
+remove_shortcut_cb (GtkMenuItem           *item,
+                   GtkFileChooserDefault *impl)
+{
+  remove_selected_bookmarks (impl);
+}
+
+static void
+rename_shortcut_cb (GtkMenuItem           *item,
+                   GtkFileChooserDefault *impl)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *cell;
+  GList *renderers;
+
+  if (shortcuts_get_selected (impl, &iter))
+    {
+      path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
+      column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0);
+      renderers = gtk_tree_view_column_get_cell_renderers (column);
+      cell = g_list_nth_data (renderers, 1);
+      g_list_free (renderers);
+      g_object_set (cell, "editable", TRUE, NULL);
+      gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
+                                       path, column, cell, TRUE);
+      gtk_tree_path_free (path);
+    }
+}
+
+/* Constructs the popup menu for the file list if needed */
+static void
+shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
+{
+  GtkWidget *item;
+
+  if (impl->browse_shortcuts_popup_menu)
+    return;
+
+  impl->browse_shortcuts_popup_menu = gtk_menu_new ();
+  gtk_menu_attach_to_widget (GTK_MENU (impl->browse_shortcuts_popup_menu),
+                            impl->browse_shortcuts_tree_view,
+                            shortcuts_popup_menu_detach_cb);
+
+  item = gtk_image_menu_item_new_with_label (_("Remove"));
+  impl->browse_shortcuts_popup_menu_remove_item = item;
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+                                gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
+  g_signal_connect (item, "activate",
+                   G_CALLBACK (remove_shortcut_cb), impl);
+  gtk_widget_show (item);
+  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
+
+  item = gtk_menu_item_new_with_label (_("Rename..."));
+  impl->browse_shortcuts_popup_menu_rename_item = item;
+  g_signal_connect (item, "activate",
+                   G_CALLBACK (rename_shortcut_cb), impl);
+  gtk_widget_show (item);
+  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
+
+  shortcuts_check_popup_sensitivity (impl);
+}
+
+static void
+shortcuts_update_popup_menu (GtkFileChooserDefault *impl)
+{
+  shortcuts_build_popup_menu (impl);  
+}
+
+static void
+popup_position_func (GtkMenu   *menu,
+                     gint      *x,
+                     gint      *y,
+                     gboolean  *push_in,
+                     gpointer  user_data);
+
+static void
+shortcuts_popup_menu (GtkFileChooserDefault *impl,
+                     GdkEventButton        *event)
+{
+  shortcuts_update_popup_menu (impl);
+  if (event)
+    gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
+                   NULL, NULL, NULL, NULL,
+                   event->button, event->time);
+  else
+    {
+      gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
+                     NULL, NULL,
+                     popup_position_func, impl->browse_shortcuts_tree_view,
+                     0, GDK_CURRENT_TIME);
+      gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu),
+                                  FALSE);
+    }
+}
+
+/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
+static gboolean
+shortcuts_popup_menu_cb (GtkWidget *widget,
+                        GtkFileChooserDefault *impl)
+{
+  shortcuts_popup_menu (impl, NULL);
+  return TRUE;
+}
+
+/* Callback used when a button is pressed on the shortcuts list.  
+ * We trap button 3 to bring up a popup menu.
+ */
+static gboolean
+shortcuts_button_press_event_cb (GtkWidget             *widget,
+                                GdkEventButton        *event,
+                                GtkFileChooserDefault *impl)
+{
+  if (event->button != 3)
+    return FALSE;
+
+  shortcuts_popup_menu (impl, event);
+  return TRUE;
+}
+
+static void
+shortcuts_edited (GtkCellRenderer       *cell,
+                 gchar                 *path_string,
+                 gchar                 *new_text,
+                 GtkFileChooserDefault *impl)
+{
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  GtkFilePath *shortcut;
+
+  g_object_set (cell, "editable", FALSE, NULL);
+
+  path = gtk_tree_path_new_from_string (path_string);
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path);
+  gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
+                     SHORTCUTS_COL_DATA, &shortcut,
+                     -1);
+  gtk_tree_path_free (path);
+  
+  gtk_file_system_set_bookmark_label (impl->file_system, shortcut, new_text);
+}
+
+static void
+shortcuts_editing_canceled (GtkCellRenderer       *cell,
+                           GtkFileChooserDefault *impl)
+{
+  g_object_set (cell, "editable", FALSE, NULL);
+}
 
 /* Creates the widgets for the shortcuts and bookmarks tree */
 static GtkWidget *
@@ -2871,6 +3062,10 @@ shortcuts_list_create (GtkFileChooserDefault *impl)
   impl->browse_shortcuts_tree_view = gtk_tree_view_new ();
   g_signal_connect (impl->browse_shortcuts_tree_view, "key-press-event",
                    G_CALLBACK (tree_view_keybinding_cb), impl);
+  g_signal_connect (impl->browse_shortcuts_tree_view, "popup-menu",
+                   G_CALLBACK (shortcuts_popup_menu_cb), impl);
+  g_signal_connect (impl->browse_shortcuts_tree_view, "button-press-event",
+                   G_CALLBACK (shortcuts_button_press_event_cb), impl);
   atk_object_set_name (gtk_widget_get_accessible (impl->browse_shortcuts_tree_view), _("Shortcuts"));
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), FALSE);
 
@@ -2935,6 +3130,10 @@ shortcuts_list_create (GtkFileChooserDefault *impl)
                                       NULL);
 
   renderer = gtk_cell_renderer_text_new ();
+  g_signal_connect (renderer, "edited", 
+                   G_CALLBACK (shortcuts_edited), impl);
+  g_signal_connect (renderer, "editing-canceled", 
+                   G_CALLBACK (shortcuts_editing_canceled), impl);
   gtk_tree_view_column_pack_start (column, renderer, TRUE);
   gtk_tree_view_column_set_attributes (column, renderer,
                                       "text", SHORTCUTS_COL_NAME,
@@ -3701,6 +3900,7 @@ bookmarks_changed_cb (GtkFileSystem         *file_system,
 
   bookmarks_check_add_sensitivity (impl);
   bookmarks_check_remove_sensitivity (impl);
+  shortcuts_check_popup_sensitivity (impl);
 }
 
 /* Sets the file chooser to multiple selection mode */
index f62e80ac3fd9b3efdd002bd4d2183166235ba2dd..1ab2f213aa6490bc7c820a0b990d61977beb8f6f 100644 (file)
@@ -772,6 +772,56 @@ gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
   return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
 }
 
+/**
+ * gtk_file_system_get_bookmark_label:
+ * @file_system: a #GtkFileSystem
+ * @path: path of the bookmark 
+ *
+ * Gets the label to display for a bookmark, or %NULL.
+ *
+ * Returns: the label for the bookmark @path
+ *
+ * Since: 2.8
+ */
+gchar *
+gtk_file_system_get_bookmark_label (GtkFileSystem     *file_system,
+                                   const GtkFilePath *path)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
+  g_return_val_if_fail (path != NULL, FALSE);
+
+  if (GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_bookmark_label)
+    return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_bookmark_label (file_system, 
+                                                                       path);
+
+  return NULL;
+}
+
+/**
+ * gtk_file_system_set_bookmark_label:
+ * @file_system: a #GtkFileSystem
+ * @path: path of the bookmark 
+ * @label: the label for the bookmark, or %NULL to display
+ *   the path itself
+ *
+ * Sets the label to display for a bookmark.
+ *
+ * Since: 2.8
+ */
+void
+gtk_file_system_set_bookmark_label (GtkFileSystem     *file_system,
+                                   const GtkFilePath *path,
+                                   const gchar       *label)
+{
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
+  g_return_val_if_fail (path != NULL, FALSE);
+
+  if (GTK_FILE_SYSTEM_GET_IFACE (file_system)->set_bookmark_label)
+    GTK_FILE_SYSTEM_GET_IFACE (file_system)->set_bookmark_label (file_system, 
+                                                                path,
+                                                                label);
+}
+
 /*****************************************
  *             GtkFileFolder             *
  *****************************************/
index ab8ab0ac08ebf96d7cbda015e6af8690082eec22..6f038fdbc6ea64a73d30bab248c81232a8391972 100644 (file)
@@ -133,7 +133,6 @@ struct _GtkFileSystemIface
 
   /* Volumes
    */
-
   void          (*volume_free)             (GtkFileSystem        *file_system,
                                            GtkFileSystemVolume  *volume);
   GtkFilePath * (*volume_get_base_path)    (GtkFileSystem        *file_system,
@@ -176,16 +175,16 @@ struct _GtkFileSystemIface
   GtkFilePath *(*filename_to_path) (GtkFileSystem      *file_system,
                                    const gchar        *path);
 
-  /* Icons */
-
+  /* Icons 
+   */
   GdkPixbuf *  (*render_icon)    (GtkFileSystem     *file_system,
                                  const GtkFilePath *path,
                                  GtkWidget         *widget,
                                  gint               pixel_size,
                                  GError           **error);
 
-  /* Bookmarks */
-
+  /* Bookmarks 
+   */
   gboolean       (*insert_bookmark)        (GtkFileSystem     *file_system,
                                            const GtkFilePath *path,
                                            gint               position,
@@ -193,12 +192,20 @@ struct _GtkFileSystemIface
   gboolean       (*remove_bookmark)        (GtkFileSystem     *file_system,
                                            const GtkFilePath *path,
                                            GError           **error);
-  GSList *       (*list_bookmarks)         (GtkFileSystem *file_system);
+  GSList *       (*list_bookmarks)         (GtkFileSystem     *file_system);
 
-  /* Signals
+  /* Signals 
    */
   void (*volumes_changed)   (GtkFileSystem *file_system);
   void (*bookmarks_changed) (GtkFileSystem *file_system);
+
+  /* Bookmark labels 
+   */
+  gchar *        (*get_bookmark_label)     (GtkFileSystem     *file_system,
+                                           const GtkFilePath *path);
+  void           (*set_bookmark_label)     (GtkFileSystem     *file_system,
+                                           const GtkFilePath *path,
+                                           const gchar       *label);
 };
 
 GType             gtk_file_system_get_type       (void) G_GNUC_CONST;
@@ -274,6 +281,11 @@ gboolean gtk_file_system_remove_bookmark (GtkFileSystem     *file_system,
                                          GError           **error);
 GSList  *gtk_file_system_list_bookmarks  (GtkFileSystem     *file_system);
 
+gchar   *gtk_file_system_get_bookmark_label (GtkFileSystem     *file_system,
+                                            const GtkFilePath *path);
+void     gtk_file_system_set_bookmark_label (GtkFileSystem     *file_system,
+                                            const GtkFilePath *path,
+                                            const gchar       *label);
 
 /*
  * Detailed information about a particular folder
index 28960cfafdf3a996339406db580834bcd158c4df..0be36681e49ac441285af37900b2f54fc37b248b 100644 (file)
@@ -42,7 +42,6 @@
 #include <time.h>
 
 #define BOOKMARKS_FILENAME ".gtk-bookmarks"
-#define BOOKMARKS_TMP_FILENAME ".gtk-bookmarks-XXXXXX"
 
 #define FOLDER_CACHE_LIFETIME 2 /* seconds */
 
@@ -192,7 +191,12 @@ static gboolean gtk_file_system_unix_insert_bookmark (GtkFileSystem     *file_sy
 static gboolean gtk_file_system_unix_remove_bookmark (GtkFileSystem     *file_system,
                                                      const GtkFilePath *path,
                                                      GError           **error);
-static GSList * gtk_file_system_unix_list_bookmarks  (GtkFileSystem *file_system);
+static GSList * gtk_file_system_unix_list_bookmarks  (GtkFileSystem     *file_system);
+static gchar  * gtk_file_system_unix_get_bookmark_label (GtkFileSystem     *file_system,
+                                                        const GtkFilePath *path);
+static void     gtk_file_system_unix_set_bookmark_label (GtkFileSystem     *file_system,
+                                                        const GtkFilePath *path,
+                                                        const gchar       *label);
 
 static GType gtk_file_folder_unix_get_type   (void);
 static void  gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class);
@@ -309,6 +313,8 @@ gtk_file_system_unix_iface_init   (GtkFileSystemIface *iface)
   iface->insert_bookmark = gtk_file_system_unix_insert_bookmark;
   iface->remove_bookmark = gtk_file_system_unix_remove_bookmark;
   iface->list_bookmarks = gtk_file_system_unix_list_bookmarks;
+  iface->get_bookmark_label = gtk_file_system_unix_get_bookmark_label;
+  iface->set_bookmark_label = gtk_file_system_unix_set_bookmark_label;
 }
 
 static void
@@ -1300,7 +1306,7 @@ gtk_file_system_unix_render_icon (GtkFileSystem     *file_system,
 }
 
 static void
-bookmark_list_free (GSList *list)
+string_list_free (GSList *list)
 {
   GSList *l;
 
@@ -1330,25 +1336,25 @@ is_local_uri (const char *uri)
 }
 
 static char *
-bookmark_get_filename (gboolean tmp_file)
+bookmark_get_filename (void)
 {
   char *filename;
 
-  filename = g_build_filename (g_get_home_dir (),
-                              tmp_file ? BOOKMARKS_TMP_FILENAME : BOOKMARKS_FILENAME,
-                              NULL);
+  filename = g_build_filename (g_get_home_dir (), BOOKMARKS_FILENAME, NULL);
+
   g_assert (filename != NULL);
+
   return filename;
 }
 
 static gboolean
-bookmark_list_read (GSList **bookmarks, GError **error)
+string_list_read (const gchar  *filename, 
+                 GSList      **bookmarks, 
+                 GError      **error)
 {
-  gchar *filename;
   gchar *contents;
   gboolean result = FALSE;
 
-  filename = bookmark_get_filename (FALSE);
   *bookmarks = NULL;
 
   if (g_file_get_contents (filename, &contents, NULL, error))
@@ -1376,25 +1382,22 @@ bookmark_list_read (GSList **bookmarks, GError **error)
       result = TRUE;
     }
 
-  g_free (filename);
-
   return result;
 }
 
 static gboolean
-bookmark_list_write (GSList *bookmarks, GError **error)
+string_list_write (gchar   *filename,
+                  GSList  *bookmarks, 
+                  GError **error)
 {
   char *tmp_filename;
-  char *filename;
   gboolean result = TRUE;
   FILE *file;
   int fd;
   int saved_errno;
 
-  /* First, write a temporary file */
-
-  tmp_filename = bookmark_get_filename (TRUE);
-  filename = bookmark_get_filename (FALSE);
+  /* First, write a temporary file */  
+  tmp_filename = g_strdup_printf ("%s-XXXXXX", filename);
 
   fd = g_mkstemp (tmp_filename);
   if (fd == -1)
@@ -1443,7 +1446,8 @@ bookmark_list_write (GSList *bookmarks, GError **error)
   g_set_error (error,
               GTK_FILE_SYSTEM_ERROR,
               GTK_FILE_SYSTEM_ERROR_FAILED,
-              _("Bookmark saving failed: %s"),
+              _("Writing %s failed: %s"),
+              filename,
               g_strerror (saved_errno));
   result = FALSE;
 
@@ -1452,12 +1456,39 @@ bookmark_list_write (GSList *bookmarks, GError **error)
 
  out:
 
-  g_free (filename);
   g_free (tmp_filename);
 
   return result;
 }
 
+static gboolean
+bookmark_list_read (GSList **bookmarks, 
+                   GError **error)
+{
+  gchar *filename;
+  gboolean result;
+
+  filename = bookmark_get_filename ();
+  result = string_list_read (filename, bookmarks, error);
+  g_free (filename);
+
+  return result;
+}
+
+static gboolean
+bookmark_list_write (GSList  *bookmarks, 
+                    GError **error)
+{
+  gchar *filename;
+  gboolean result;
+
+  filename = bookmark_get_filename ();
+  result = string_list_write (filename, bookmarks, error);
+  g_free (filename);
+  
+  return result;
+}
+
 static gboolean
 gtk_file_system_unix_insert_bookmark (GtkFileSystem     *file_system,
                                      const GtkFilePath *path,
@@ -1487,10 +1518,19 @@ gtk_file_system_unix_insert_bookmark (GtkFileSystem     *file_system,
 
   for (l = bookmarks; l; l = l->next)
     {
-      const char *bookmark;
+      char *bookmark, *space;
 
       bookmark = l->data;
-      if (strcmp (bookmark, uri) == 0)
+      
+      space = strchr (bookmark, ' ');
+      if (space)
+       *space = '\0';
+      if (strcmp (bookmark, uri) != 0)
+       {
+         if (space)
+           *space = ' ';
+       }
+      else
        {
          g_set_error (error,
                       GTK_FILE_SYSTEM_ERROR,
@@ -1511,7 +1551,7 @@ gtk_file_system_unix_insert_bookmark (GtkFileSystem     *file_system,
  out:
 
   g_free (uri);
-  bookmark_list_free (bookmarks);
+  string_list_free (bookmarks);
 
   return result;
 }
@@ -1535,10 +1575,19 @@ gtk_file_system_unix_remove_bookmark (GtkFileSystem     *file_system,
 
   for (l = bookmarks; l; l = l->next)
     {
-      const char *bookmark;
+      char *bookmark, *space;
 
-      bookmark = l->data;
-      if (strcmp (bookmark, uri) == 0)
+      bookmark = (char *)l->data;
+      space = strchr (bookmark, ' ');
+      if (space)
+       *space = '\0';
+
+      if (strcmp (bookmark, uri) != 0)
+       {
+         if (space)
+           *space = ' ';
+       }
+      else
        {
          g_free (l->data);
          bookmarks = g_slist_remove_link (bookmarks, l);
@@ -1547,7 +1596,8 @@ gtk_file_system_unix_remove_bookmark (GtkFileSystem     *file_system,
          if (bookmark_list_write (bookmarks, error))
            {
              result = TRUE;
-             g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
+
+             g_signal_emit_by_name (file_system, "bookmarks-changed", 0);            
            }
 
          goto out;
@@ -1563,7 +1613,7 @@ gtk_file_system_unix_remove_bookmark (GtkFileSystem     *file_system,
  out:
 
   g_free (uri);
-  bookmark_list_free (bookmarks);
+  string_list_free (bookmarks);
 
   return result;
 }
@@ -1582,20 +1632,109 @@ gtk_file_system_unix_list_bookmarks (GtkFileSystem *file_system)
 
   for (l = bookmarks; l; l = l->next)
     {
-      const char *name;
+      char *bookmark, *space;
 
-      name = l->data;
+      bookmark = (char *)l->data;
+      space = strchr (bookmark, ' ');
+      if (space)
+       *space = '\0';
 
-      if (is_local_uri (name))
-       result = g_slist_prepend (result, gtk_file_system_unix_uri_to_path (file_system, name));
+      if (is_local_uri (bookmark))
+       result = g_slist_prepend (result, gtk_file_system_unix_uri_to_path (file_system, bookmark));
     }
 
-  bookmark_list_free (bookmarks);
+  string_list_free (bookmarks);
 
   result = g_slist_reverse (result);
   return result;
 }
 
+static gchar *
+gtk_file_system_unix_get_bookmark_label (GtkFileSystem     *file_system,
+                                        const GtkFilePath *path)
+{
+  GSList *labels;
+  gchar *label;
+  GSList *l;
+  char *bookmark, *space, *uri;
+  
+  labels = NULL;
+  label = NULL;
+
+  uri = gtk_file_system_path_to_uri (file_system, path);
+  bookmark_list_read (&labels, NULL);
+
+  for (l = labels; l && !label; l = l->next) 
+    {
+      bookmark = (char *)l->data;
+      space = strchr (bookmark, ' ');
+      if (!space)
+       continue;
+
+      *space = '\0';
+
+      if (strcmp (uri, bookmark) == 0)
+       label = g_strdup (space + 1);
+    }
+
+  string_list_free (labels);
+  g_free (uri);
+
+  return label;
+}
+
+static void
+gtk_file_system_unix_set_bookmark_label (GtkFileSystem     *file_system,
+                                        const GtkFilePath *path,
+                                        const gchar       *label)
+{
+  GSList *labels;
+  GSList *l;
+  gchar *bookmark, *space, *uri;
+  gboolean found;
+
+  labels = NULL;
+
+  uri = gtk_file_system_path_to_uri (file_system, path);
+  bookmark_list_read (&labels, NULL);
+
+  found = FALSE;
+  for (l = labels; l && !found; l = l->next) 
+    {
+      bookmark = (gchar *)l->data;
+      space = strchr (bookmark, ' ');
+      if (space)
+       *space = '\0';
+
+      if (strcmp (bookmark, uri) != 0)
+       {
+         if (space)
+           *space = ' ';
+       }
+      else
+       {
+         g_free (bookmark);
+         
+         if (label && *label)
+           l->data = g_strdup_printf ("%s %s", uri, label);
+         else
+           l->data = g_strdup (uri);
+
+         found = TRUE;
+         break;
+       }
+    }
+
+  if (found)
+    {
+      if (bookmark_list_write (labels, NULL))
+       g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
+    }
+  
+  string_list_free (labels);
+  g_free (uri);
+}
+
 /*
  * GtkFileFolderUnix
  */